/*
 *    Copyright 2009-2023 the original author or authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       https://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.apache.ibatis.executor.statement;

import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;

import org.apache.ibatis.builder.StaticSqlSource;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMap;
import org.apache.ibatis.mapping.ResultMap;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.ryan.utils.PageHoder;
import org.apache.ibatis.session.Configuration;

/**
 * Utility for {@link java.sql.Statement}.
 *
 * @since 3.4.0
 *
 * @author Kazuki Shimizu
 */
public class StatementUtil {

  private StatementUtil() {
    // NOP
  }

  /**
   * Apply a transaction timeout.
   * <p>
   * Update a query timeout to apply a transaction timeout.
   * </p>
   *
   * @param statement
   *          a target statement
   * @param queryTimeout
   *          a query timeout
   * @param transactionTimeout
   *          a transaction timeout
   *
   * @throws SQLException
   *           if a database access error occurs, this method is called on a closed <code>Statement</code>
   */
  public static void applyTransactionTimeout(Statement statement, Integer queryTimeout, Integer transactionTimeout)
      throws SQLException {
    if (transactionTimeout == null) {
      return;
    }
    if (queryTimeout == null || queryTimeout == 0 || transactionTimeout < queryTimeout) {
      statement.setQueryTimeout(transactionTimeout);
    }
  }

  /**
   * // todo 暂时不知道干啥的
   *
   * @param config
   * @param oldId
   * @param dataSql
   *
   * @return
   */
  public static MappedStatement preparePagedStatement(Configuration config, String oldId, BoundSql dataSql) {
    String sql = String.format("SELECT count(1)  FROM (%s) alias ", new Object[] { dataSql.getSql() });
    String id = String.format("selectCount-%s", new Object[] { oldId });
    ResultMap rm = (new ResultMap.Builder(config, "defaultResultMap", Integer.class,
        Arrays.asList(new org.apache.ibatis.mapping.ResultMapping[0]))).build();
    ParameterMap parameterMap = (new ParameterMap.Builder(config, "defaultParameterMap",
        dataSql.getParameterObject().getClass(), dataSql.getParameterMappings())).build();

    MappedStatement ms = (new MappedStatement.Builder(config, id, (SqlSource) new StaticSqlSource(config, sql),
        SqlCommandType.SELECT)).parameterMap(parameterMap).resultMaps(Arrays.asList(new ResultMap[] { rm })).build();
    return ms;
  }

  public static MappedStatement preparePagedDataStatement(Configuration config, MappedStatement oldMs,
      BoundSql dataSql) {
    int start = (PageHoder.getPageNo().intValue() - 1) * PageHoder.getPageSize().intValue();
    String sql = String.format("SELECT *  FROM (%s) alias_table  LIMIT  %s , %s ",
        new Object[] { dataSql.getSql(), Integer.valueOf(start), PageHoder.getPageSize() });

    String id = ((ResultMap) oldMs.getResultMaps().get(0)).getId();
    ParameterMap parameterMap = (new ParameterMap.Builder(config, "defaultParameterMap",
        dataSql.getParameterObject().getClass(), dataSql.getParameterMappings())).build();

    MappedStatement ms = (new MappedStatement.Builder(config, id, (SqlSource) new StaticSqlSource(config, sql),
        SqlCommandType.SELECT)).parameterMap(parameterMap).resultMaps(oldMs.getResultMaps()).build();
    return ms;
  }

}
